package model;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import javax.swing.JProgressBar;

import model.BinSetVariables;
/**
 * 
 * @author Estelle && Marie
 * 
 * Here, we make the operation of our montecarlo
 *
 */

public class MonteCarloSimulationThreads {
	
	Double Sum;
	BinSetVariables a ;
	JProgressBar barre;
	
	public MonteCarloSimulationThreads(BinSetVariables b, JProgressBar bar){
		
		this.a = b;
		this.Sum=0.0;
		this.barre = bar;
		barre.setMaximum(a.getnSimulations());
		
	}
	
	public double MonteCarloStandardOption(){
		
		int z=0;
		
		if (a.getCallPutFlag().compareTo("c")==0){
			z=1;
		}
		else if (a.getCallPutFlag().compareTo("p")==0){
			z=-1;
		}

		int proc = Runtime.getRuntime().availableProcessors();
			
		ArrayList <Callable <Double> > partitions = new ArrayList<Callable <Double>>();
		ExecutorService executorPool = Executors.newFixedThreadPool((int) (proc/(1-0.1)));			
		
		ConcurrentHashMap<String, Long> nbOfThread = new  ConcurrentHashMap<String, Long> (); 
	
		
		for (int i=0;i< a.getnSimulations();i++) {

				
			barre.setValue(i);	
			
			partitions.add(new CallablePrice(a,z,barre, nbOfThread));
			
		}
		
		try {
					
			
			List<Future<Double>> price = executorPool.invokeAll(partitions, 10000, TimeUnit.SECONDS);				
			
			for (int i=0;i< a.getnSimulations();i++) {						    	
				
				Sum = Sum + price.get(i).get();							
				
			}	
			
			System.out.println("Numbers of threads runned (MonteCarloSimulation.java ligne 78) :"+ nbOfThread.size());
			
			for (ConcurrentHashMap.Entry entry : nbOfThread.entrySet()) {
			    System.out.println("(MonteCarloSimulation.java ligne 78) " + entry.getKey() + ", " + entry.getValue());
			}
			
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}					    
		
		return Math.exp(-a.getR()*a.getT()) * (Sum / a.getnSimulations());
	}
	

}
